home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
676-700
/
699
/
iffconvert
/
src
/
iffpack.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
18KB
|
646 lines
/**************************************************************************
* *
* iffpack *
* *
* Routines for loading and saving pictures with windows *
* using the old formats and the new compression format *
* *
**************************************************************************/
#include <intuition/intuition.h>
#include <functions.h>
#include <stdio.h>
#define NOERRORTEXT
#include "iffpack.h"
#define BADFLAGS (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)
#define FLAGMASK (~BADFLAGS)
#define CAMGMASK (FLAGMASK & 0xffffL)
struct BMHD {
ULONG Size;
USHORT Width,Height;
SHORT LeftEdge,TopEdge;
UBYTE Depth;
UBYTE Mask;
UBYTE Compression;
UBYTE Pad;
USHORT Transparent;
UBYTE XAspect,YAspect;
SHORT ScrWidth,ScrHeight;
};
static USHORT buf[256];
static short count,runlen,ptr;
static short rows,bytes,depth;
static cmode;
static short TempY=0,TempX=0;
static struct BitMap MyBm;
static struct RastPort MyRast;
static short anzcolors;
static USHORT colors[32];
/**************************************************************************
* *
* SetColors(vp): *
* *
* Set the colors, that were previously loaded with ReadPicSize *
* *
* vp: Viewport of the Screen *
* *
**************************************************************************/
SetColors(vp)
struct ViewPort *vp;
{
LoadRGB4(vp,colors,(long)anzcolors);
}
/**************************************************************************
* *
* ReadPicSize(fp,winx,winy,srcx,srcy,depth,vmode *
* *
* Read the size and viewmode of the picture and load the colors to an *
* internal buffer *
* *
* fp: FILE-Pointer of stdio *
* winx,winy: references to the size of the window *
* srcx,srcy: references to the size of the screen *
* depth: reference to the depth of the screen *
* vmode: reference to Viewmode *
* *
* ReadPicSize sets the values of the referenced parameters *
* *
* the result of ReadPicSize is 0 if no error occured or an error-code *
* defined in iffpack.h *
* *
**************************************************************************/
ReadPicSize(fp,winx,winy,scrx,scry,depth,vmode)
FILE *fp;
SHORT *winx,*winy;
SHORT *scrx,*scry;
SHORT *depth;
USHORT *vmode;
{
struct BMHD bmhd;
int err;
if(err=ReadHeader(fp,&bmhd,vmode)) return(err);
*winx=bmhd.Width;
*winy=bmhd.Height;
*scrx=bmhd.ScrWidth;
*scry=bmhd.ScrHeight;
*depth=bmhd.Depth;
return(0);
}
/**************************************************************************
* *
* ReadBody: read the bitmap data to a rastport *
* *
* rp: pointer to rastport *
* *
* fp: FILE-Pointer of stdio *
* *
**************************************************************************/
ReadBody(rp,fp)
struct RastPort *rp;
FILE *fp;
{
long size;
short x,y,p;
int c;
if(!fread(&size,4,1,fp)) return(BAD_IFF);
if(cmode==0) { /* Compression mode 0: no compression */
for(y=0;y<rows;y++) {
for(p=0;p<depth;p++) {
for(x=0;x<bytes;x++) {
if((c=getc(fp))==EOF) return(BAD_IFF);
MyBm.Planes[p][x]=c;
}
}
ClipBlit(&MyRast,0L,0L,rp,0L,(long)y,(long)TempX,1L,192L);
WaitBlit();
}
} else if(cmode==1) { /* Compression mode 1: normal compression */
for(y=0;y<rows;y++) {
for(p=0;p<depth;p++) {
for(x=0;x<bytes;x++) {
if((c=compget(fp))==EOF) return(BAD_IFF);
if(c<256) {
MyBm.Planes[p][x]=c;
}
}
}
ClipBlit(&MyRast,0L,0L,rp,0L,(long)y,(long)TempX,1L,192L);
WaitBlit();
}
} else if(cmode==2) { /* Compression mode 2: new compression */
for(x=0;x<bytes;x++) {
for(p=0;p<depth;p++) {
for(y=0;y<rows;y++) {
if((c=compget(fp))==EOF) return(BAD_IFF);
if(c<256) {
MyBm.Planes[p][y<<1]=c;
}
}
}
ClipBlit(&MyRast,0L,0L,rp,(long)(x<<3),0L,8L,(long)TempY,192L);
WaitBlit();
}
}
IFFCleanup();
return(0);
}
/**************************************************************************
* *
* WriteWindow(fp,w,mode): *
* *
* Write the window win to the file with FILE-Pointer fp using the *
* compression method mode *
* *
**************************************************************************/
WriteWindow(fp,w,mode)
FILE *fp;
struct Window *w;
short mode;
{
if(mode<0 || mode>2) return(UNKNOWN_COMPRESSION);
if(WriteBMHD(w,fp,mode)) return(WRITE_ERROR);
if(WriteCMAP(w->WScreen,fp)) return(WRITE_ERROR);
if(WriteCAMG(w->WScreen,fp)) return(WRITE_ERROR);
if(initcomp((short)w->Width,(short)w->Height,(short)w->WScreen->BitMap.Depth,
mode)) return(NO_MEMORY);
if(WriteBODY(w,fp,mode)) return(WRITE_ERROR);
IFFCleanup();
return(0);
}
/**************************************************************************
* *
* IFF-Cleanup: frees all allocated memory *
* *
**************************************************************************/
IFFCleanup()
{
short a;
if(TempX) {
for(a=0;a<8;a++) {
if(MyBm.Planes[a])
FreeRaster(MyBm.Planes[a],(long)TempX,(long)TempY);
}
}
TempX=TempY=0;
}
/***********************************
* *
* internal functions: *
* *
***********************************/
/* ReadHeader: read size-information, viewmode and colors */
static ReadHeader(fp,bmhd,viewmode)
FILE *fp;
struct BMHD *bmhd;
USHORT *viewmode;
{
short status=0;
long id[3],sid,size;
if(!fread(id,12,1,fp)) return(BAD_IFF);
if(id[0]!='FORM') return(BAD_IFF);
if(id[2]!='ILBM') return(BAD_IFF);
*viewmode=0;
do {
if(!fread(&sid,4,1,fp)) return(BAD_IFF);
if(sid=='CMAP') {
if(status&1) return(BAD_IFF); /* doppelt */
if(ReadCMAP(fp)) return(BAD_IFF);
status|=1;
} else if(sid=='CAMG') {
if(status&2) return(BAD_IFF); /* doppelt */
if(ReadCAMG(fp,viewmode)) return(BAD_IFF);
status|=2;
} else if(sid=='BMHD') {
if(status&4) return(BAD_IFF); /* doppelt */
if(ReadBMHD(fp,bmhd,viewmode)) return(BAD_IFF);
status|=4;
} else if(sid!='BODY') {
if(!fread(&size,4,1,fp)) return(BAD_IFF);
size+=size&1;
if(fseek(fp,size,1)) return(BAD_IFF);
}
} while(sid!='BODY');
if(!(status&1) || !(status&4)) return(BAD_IFF); /* Daten fehlen */
if(initcomp((short)bmhd->Width,(short)bmhd->Height,(short)bmhd->Depth,
(short)bmhd->Compression)) return(NO_MEMORY);
rows=bmhd->Height;
bytes=((bmhd->Width+15)>>3)&0xfffe;
depth=bmhd->Depth;
cmode=bmhd->Compression;
if(cmode<0 || cmode>2) return(UNKNOWN_COMPRESSION);
return(0);
}
/* Read chunk BMHD */
static ReadBMHD(fp,bmhd,vmode)
FILE *fp;
struct BMHD *bmhd;
USHORT *vmode;
{
if(!fread(bmhd,sizeof(struct BMHD),1,fp)) return(BAD_IFF);
if(bmhd->Size!=20) return(BAD_IFF);
*vmode=0;
if(bmhd->Width>400 && bmhd->Depth<=4) *vmode|=HIRES;
if(bmhd->Height>300) *vmode|=LACE;
if(bmhd->Depth>6) *vmode|=HAM;
return(0);
}
/* read colormap */
static ReadCMAP(fp)
FILE *fp;
{
long size;
short a;
int r,g,b;
if(!fread(&size,4,1,fp)) return(1);
if(size % 3) return(1);
size/=3;
anzcolors=size;
for(a=0;a<size;a++) {
if((r=getc(fp))==EOF) return(1);
if((g=getc(fp))==EOF) return(1);
if((b=getc(fp))==EOF) return(1);
r&=0xf0;
g&=0xf0;
b&=0xf0;
colors[a]=(r<<4)|g|(b>>4);
}
return(0);
}
/* read viewmode */
static ReadCAMG(fp,vmode)
FILE *fp;
USHORT *vmode;
{
long a;
long size;
if(!fread(&size,4,1,fp)) return(1);
if(size!=4) return(1);
if(!fread(&a,4,1,fp)) return(1);
*vmode=a&CAMGMASK;
return(0);
}
/* write BMHD */
static WriteBMHD(w,fp,mode)
struct Window *w;
FILE *fp;
short mode;
{
struct BMHD bm;
if(!fwrite("FORM ILBMBMHD",16,1,fp)) return(1);
bm.Size=20;
bm.Width=w->Width;
bm.Height=w->Height;
bm.ScrWidth=w->WScreen->Width;
bm.ScrHeight=w->WScreen->Height;
bm.LeftEdge=bm.TopEdge=0;
bm.Depth=w->WScreen->BitMap.Depth;
bm.Mask=bm.Pad=0;
bm.Compression=mode;
bm.Transparent=0;
bm.YAspect=11;
bm.XAspect=10;
if((w->WScreen->ViewPort.Modes&LACE) && !(w->WScreen->ViewPort.Modes&HIRES)) bm.XAspect=20;
if(!(w->WScreen->ViewPort.Modes&LACE) && (w->WScreen->ViewPort.Modes&HIRES)) bm.XAspect=5;
if(!fwrite(&bm,sizeof(struct BMHD),1,fp)) return(1);
return(0);
}
/* write colormap */
static WriteCMAP(s,fp)
struct Screen *s;
FILE *fp;
{
long size;
short anz,col;
short i;
int c;
if(!fwrite("CMAP",4,1,fp)) return(1);
anz=s->BitMap.Depth;
anz=1<<anz;
if(anz>32) anz=32;
size=3*anz;
if(!fwrite(&size,4,1,fp)) return(1);
for(i=0;i<anz;i++) {
col=GetRGB4(s->ViewPort.ColorMap,(long)i);
c=((col>>8)&0xf)<<4;
if(putc(c,fp)==EOF) return(1);
c=((col>>4)&0xf)<<4;
if(putc(c,fp)==EOF) return(1);
c=(col&0xf)<<4;
if(putc(c,fp)==EOF) return(1);
}
return(0);
}
/* write viewmode */
static WriteCAMG(s,fp)
struct Screen *s;
FILE *fp;
{
long a;
if(!fwrite("CAMG",4,1,fp)) return(1);
a=4;
if(!fwrite(&a,4,1,fp)) return(1);
a=s->ViewPort.Modes;
a&=CAMGMASK;
if(!fwrite(&a,4,1,fp)) return(1);
return(0);
}
/* write bitmaps */
static WriteBODY(w,fp,mode)
struct Window *w;
FILE *fp;
short mode;
{
struct RastPort *rp;
struct BitMap *bm;
short bytes,rows;
long pos;
long size,bodysize,depth;
short x,y,p;
UBYTE *plane;
rp=w->RPort;
if(!fwrite("BODY ",8,1,fp)) return(1);
pos=ftell(fp);
bm=MyRast.BitMap;
bytes=((w->Width+15)>>3) & 0xfffe;
rows=w->Height;
depth=bm->Depth;
if(mode==2) {
for(x=0;x<bytes;x++) {
if(x) {
ClipBlit(rp,(x-1L)<<3L,0L,&MyRast,0L,0L,16L,(long)TempY,192L);
WaitBlit();
} else {
ClipBlit(rp,0L,0L,&MyRast,8L,0L,8L,(long)TempY,192L);
WaitBlit();
}
for(p=0;p<depth;p++) {
if(comprow(fp,rows,x,p)) return(1);
}
}
} else if(mode==1) {
for(y=0;y<rows;y++) {
if(y) {
ClipBlit(rp,0L,(long)y-1L,&MyRast,0L,0L,(long)TempX,2L,192L);
WaitBlit();
} else {
ClipBlit(rp,0L,0L,&MyRast,0L,1L,(long)TempX,1L,192L);
WaitBlit();
}
for(p=0;p<depth;p++) {
if(compline(fp,bytes,y,p)) return(1);
}
}
} else {
for(y=0;y<rows;y++) {
ClipBlit(rp,0L,(long)y,&MyRast,0L,0L,(long)TempX,1L,192L);
WaitBlit();
for(p=0;p<depth;p++) {
plane=MyBm.Planes[p];
for(x=0;x<bytes;x++) {
if(putc((int)(plane[x]),fp)==EOF) return(1);
}
}
}
}
size=ftell(fp);
bodysize=size-pos;
if(fseek(fp,pos-4L,0)) return(1);
if(!fwrite(&bodysize,4,1,fp)) return(1);
if(fseek(fp,4L,0)) return(1);
size-=8;
if(!fwrite(&size,4,1,fp)) return(1);
return(0);
}
/* compress one line */
static compline(fp,bytes,y,p)
FILE *fp;
short bytes;
short y,p;
{
short x,x2,x3,lx;
short found;
short a;
UBYTE * ptr;
UBYTE *lptr;
ptr=&MyBm.Planes[p][bytes];
lptr=MyBm.Planes[p];
lx=0;
for(x=0;x<bytes;x++) {
x2=x;
found=0; /* count bytes with equal value */
while(ptr[x2]==ptr[x2+1] && x2<bytes-1 && x2-x<127) x2++;
x2++;
if((x-lx)==0 && x2-x>=2 || x2-x>=3) {
if(x-lx) {
/* save uncompressed bytes */
if(putc((int)(x-lx-1),fp)==EOF) return(1);
for(a=lx;a<x;a++) if(putc((int)ptr[a],fp)==EOF) return(1);
}
/* save compressed bytes */
if(putc(x-x2+1,fp)==EOF) return(1);
if(putc((int)ptr[x],fp)==EOF) return(1);
x=x2-1;
found=1;
}
if(found) {
lx=x+1;
} else {
if(x-lx==127) {
/* save uncompressed bytes */
if(fputc(127,fp)==EOF) return(1);
for(a=lx;a<=x;a++) if(putc(ptr[a],fp)==EOF) return(1);
lx=x+1;
}
}
}
if(lx<bytes) {
if(putc(bytes-lx-1,fp)==EOF) return(1);
for(a=lx;a<bytes;a++) if(putc((int)ptr[a],fp)==EOF) return(1);
}
return(0);
}
/* compress one column (width: 8 bit) */
static comprow(fp,rows,x,p)
FILE *fp;
short rows;
short x,p;
{
short y,y2,y3,ly;
short found;
short a;
UBYTE * ptr;
ptr=MyBm.Planes[p];
ly=0;
for(y=0;y<rows;y++) {
y3=y2=y;
found=0; /* count bytes with equal value */
while(ptr[(y2<<1)+1]==ptr[(y2<<1)+3] && y2<rows-1 &&
y2-y<127) y2++;
y2++;
if(x) {
/* compare with previous column */
while(ptr[y3<<1]==ptr[(y3<<1)+1] && y3<rows &&
y3-y<256) y3++;
}
if(y2>=y3) {
if(y-ly==0 && y2-y>=2 || y2-y>=3) {
if(y-ly) {
/* write uncompressed data */
if(putc(y-ly-1,fp)==EOF) return(1);
for(a=ly;a<y;a++)
if(putc((int)ptr[(a<<1)+1],fp)==EOF) return(1);
}
/* write compressed data: Byte-Run */
if(putc(y-y2+1,fp)==EOF) return(1);
if(putc((int)ptr[(y<<1)+1],fp)==EOF) return(1);
y=y2-1;
found=1;
}
} else {
if(!y-ly && y3-y>=2 || y3-y>=3) {
if(y-ly) {
/* write uncompressed data */
if(putc(y-ly-1,fp)==EOF) return(1);
for(a=ly;a<y;a++)
if(putc((int)ptr[(a<<1)+1],fp)==EOF) return(1);
}
/* write compressed data: copy previous column */
if(putc(128,fp)==EOF) return(1);
if(putc(y3-y-1,fp)==EOF) return(1);
y=y3-1;
found=1;
}
}
if(found) {
ly=y+1;
} else {
if(y-ly==127) {
/* write uncompressed data */
if(fputc(127,fp)==EOF) return(1);
for(a=ly;a<=y;a++)
if(putc(ptr[(a<<1)+1],fp)==EOF) return(1);
ly=y+1;
}
}
}
if(ly<rows) {
if(putc(rows-ly-1,fp)==EOF) return(1);
for(a=ly;a<rows;a++)
if(putc((int)ptr[(a<<1)+1],fp)==EOF) return(1);
}
return(0);
}
/* init compression */
static initcomp(width,height,depth,mode)
short width,height,depth,mode;
{
short a;
if(TempX) IFFCleanup();
if(mode!=2) {
TempX=width;
TempY=2;
InitRastPort(&MyRast);
InitBitMap(&MyBm,(long)depth,(long)width,2L);
for(a=0;a<8;a++) MyBm.Planes[a]=0;
for(a=0;a<depth;a++) {
if(!(MyBm.Planes[a]=AllocRaster((long)width,2L))) return(NO_MEMORY);
}
} else {
TempX=16;
TempY=height;
InitRastPort(&MyRast);
InitBitMap(&MyBm,(long)depth,16L,(long)height);
for(a=0;a<8;a++) MyBm.Planes[a]=0;
for(a=0;a<depth;a++) {
if(!(MyBm.Planes[a]=AllocRaster(16L,(long)height))) return(NO_MEMORY);
}
}
MyRast.BitMap=&MyBm;
count=ptr=0;
runlen=1;
return(0);
}
/* uncompress bitplanes */
static compget(fp)
FILE *fp;
{
int c;
char cc;
UBYTE val;
if(ptr>=count) {
if((c=getc(fp))==EOF) return(EOF);
cc=c;
ptr=0;
if(c==128) { /* code for copying columns */
if((c=getc(fp))==EOF) return(EOF);
count=c+1; /* count shorts of 256 (value indicating copy mode) */
for(c=0;c<count;c++) buf[c]=256;
} else if(cc>=0) { /* read uncompressed data */
count=cc+1;
for(c=0;c<count;c++) if((buf[c]=getc(fp))==EOF) return(EOF);
} else {
count=-cc+1; /* read compressed data and uncompress it */
if((c=getc(fp))==EOF) return(EOF);
val=c;
for(c=0;c<count;c++) buf[c]=val;
}
}
if(ptr>=count) return(EOF);
return(buf[ptr++]);
}